package business.global.pk.nn;

import business.global.pk.sss.SSSLogic;

import java.util.*;

public class NNGameLogic {
    public final static int MAX_COUNT = 5;
    // 扑克类型
    public final static int OX_VALUE0 = 0; // 混合牌型

    // public final static int OX_THREE_SAME =101; //三条牌型
    public final static int OX_FOURKING = 102; // 银牛 10 +4jqk
    public final static int OX_SHUNZI = 103; // 顺子牛
    public final static int OX_FIVEKING = 104; // 金牛 五张都是10以上 五花牛
    public final static int OX_TONGHUA = 105; // 同花牛
    public final static int OX_HULU = 106; // 葫芦牛
    public final static int OX_FOUR_SAME = 107; // 四条牌型 炸弹
    public final static int OX_FIVE_SMALL = 108; // 5小牌
    public final static int OX_TONGHUASHUN = 109; // 快乐牛
    private static SSSLogic logic;

    // 获取牌值
    public static Integer GetCardValue(Integer card) {
        return BasePocker.getCardValue(card);
    }

    // 获取牌值
    public static Integer GetCardValue2(Integer card) {
        return BasePocker.getCardValue(card) > 10 ? 10 : BasePocker.getCardValue(card);
    }

    // 获取牌颜色
    public static Integer GetCardColor(Integer card) {
        return BasePocker.getCardColor(card);
    }

    // 获取类型
    @SuppressWarnings({ "unchecked", "unused" })
    public static int GetCardType(ArrayList<Integer> list, int laizi) {
        int result = GetOxCard(list, laizi);

        // 5小牌
        Integer cbCardCount = (Integer) list.size();
        Integer smallCardNum = 0, smallCardSum = 0;
        for (int i = 0; i < MAX_COUNT; i++) {

            if (GetCardValue(list.get(i)) < 5) {
                smallCardNum++;
                if (GetCardLogicValue(list.get(i)) == GetCardLogicValue(laizi)
                        || BasePockerLogic.isTrump(list.get(i))) {
                    smallCardSum++;
                } else {
                    smallCardSum += GetCardValue(list.get(i));
                }
            } else
                break;

        }
        int[] cardArray = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            cardArray[i] = list.get(i);
            if (GetCardValue(list.get(i)) == GetCardValue(laizi)) {
                cardArray[i] = 0x41;
            }
        }

        logic = new SSSLogic();
        int type = logic.GetCardType(cardArray, list.size(), 0);
        if (SSSLogic.CT_FIVE_STRAIGHT_FLUSH_NO_A == type
                || SSSLogic.CT_FIVE_STRAIGHT_FLUSH_FIRST_A == type || SSSLogic.CT_FIVE_STRAIGHT_FLUSH_BACK_A == type) {
            return OX_TONGHUASHUN;
        }

        if (smallCardSum <= 10 && smallCardNum == 5)
            return OX_FIVE_SMALL;

        if (SSSLogic.CT_FIVE_FOUR_ONE == type) {
            return OX_FOUR_SAME;
        }

        if (SSSLogic.CT_FIVE_THREE_DEOUBLE == type) {
            return OX_HULU;
        }

        if (SSSLogic.CT_FIVE_FLUSH == type || SSSLogic.CT_FIVE_FLUSH_DOUBLE == type
                || SSSLogic.CT_FIVE_FLUSH_TWO_DOUBLE == type) {
            return OX_TONGHUA;
        }
        //// 炸弹牌型
        Integer bSameCount = 0;
        ArrayList<Integer> tempCardData = (ArrayList<Integer>) list.clone();

        tempCardData.sort(sorter);
        Integer bSecondValue = GetCardValue(tempCardData.get(MAX_COUNT / 2));
        for (Integer i = 0; i < cbCardCount; i++) {
            if (bSecondValue == GetCardValue(tempCardData.get(i))) {
                bSameCount++;
            }
        }
        if (bSameCount == 4)
            return OX_FOUR_SAME;

        Integer bKingCount = 0, bTenCount = 0;
        for (Integer i = 0; i < cbCardCount; i++) {
            if (GetCardValue(list.get(i)) > 10) {
                bKingCount++;
            } else if (GetCardValue(list.get(i)) == 10) {
                bTenCount++;
            }
        }
        if (bKingCount == MAX_COUNT)
            return OX_FIVEKING;

        if (SSSLogic.CT_FIVE_MIXED_FLUSH_NO_A == type
                || SSSLogic.CT_FIVE_MIXED_FLUSH_FIRST_A == type || SSSLogic.CT_FIVE_MIXED_FLUSH_BACK_A == type) {
            return OX_SHUNZI;
        }

        if (bKingCount == MAX_COUNT - 1 && bTenCount == 1)
            return OX_FOURKING;

        return result;
    }

    // 获取牛牛 zhaozw 1-2个癞子的情况
    @SuppressWarnings("unchecked")
    public static int GetOxCard(ArrayList<Integer> list, int laizi) {
        // Collections.sort(list,new Comparator<Integer>() {
        // @Override
        // public int compare(Integer o1, Integer o2) {
        // if(GetCardValue(o1) == GetCardValue(laizi)&&laizi!=0 ||
        // BasePockerLogic.isTrump(o1)){
        // return 1;
        // }
        // if(GetCardValue(o2) == GetCardValue(laizi)&&laizi!=0 ||
        // BasePockerLogic.isTrump(o2)){
        // return -1;
        // }
        // return GetCardLogicValue(o1) - GetCardLogicValue(o2);
        // }
        // });
        list.sort(jsproto.c2s.cclass.pk.BasePockerLogic.sorterBigToSmallHaveTrump);
        ArrayList<Integer> bTemp = new ArrayList<Integer>(list.size());
        ArrayList<Integer> bTempData = (ArrayList<Integer>) list.clone();
        Integer bSum = 0;
        int laiziNum = 0;
        for (Integer i = 0; i < list.size(); i++) {
            bTemp.add(i, GetCardLogicValue(list.get(i)));
            if (GetCardValue(list.get(i)) == GetCardValue(laizi) && laizi != 0
                    || BasePockerLogic.isTrump(list.get(i))) {
                laiziNum++;
            } else {
                bSum += bTemp.get(i);
            }
        }

        if (laiziNum >= 2) {

            if (GetCardValue(list.get(4)) == GetCardValue(laizi) && laizi != 0 || BasePockerLogic.isTrump(list.get(4))
                    || GetCardValue(list.get(3)) == GetCardValue(laizi) && laizi != 0
                    || BasePockerLogic.isTrump(list.get(3))) {

                if ((GetCardValue(list.get(4)) == GetCardValue(laizi) && laizi != 0
                        || BasePockerLogic.isTrump(list.get(4)))
                        && (GetCardValue(list.get(3)) == GetCardValue(laizi) && laizi != 0
                                || BasePockerLogic.isTrump(list.get(3)))) {

                    for (int i = 0; i < 3; i++) {
                        if (GetCardValue(list.get(i)) == GetCardValue(laizi) && laizi != 0
                                || BasePockerLogic.isTrump(list.get(i))) {
                        } else {

                            list.set(i, bTempData.get(4));
                            list.set(4, bTempData.get(i));
                            return 10;
                        }
                    }
                }
            } else {
                for (int i = 0; i < 3; i++) {
                    if (GetCardValue(list.get(i)) == GetCardValue(laizi) && laizi != 0
                            || BasePockerLogic.isTrump(list.get(i))) {
                        list.set(i, bTempData.get(4));
                        list.set(4, bTempData.get(i));
                        return 10;
                    }
                }
            }
            return 10;
        } else if (laiziNum == 2) {

            int laiziNum2 = 0;
            for (Integer i = 0; i < 3; i++) {
                if (GetCardValue(list.get(i)) == GetCardValue(laizi) && laizi != 0
                        || BasePockerLogic.isTrump(list.get(i))) {
                    laiziNum2++;
                }
            }
            if (laiziNum2 == 0) {
                list.set(0, bTempData.get(3));
            } else if (laiziNum2 == 2) {
                if (GetCardValue(list.get(0)) == GetCardValue(laizi) && laizi != 0
                        || BasePockerLogic.isTrump(list.get(0))) {
                    if (GetCardValue(list.get(3)) == GetCardValue(laizi) && laizi != 0
                            || BasePockerLogic.isTrump(list.get(3))) {
                        list.set(0, bTempData.get(4));
                        list.set(4, bTempData.get(0));
                    } else {
                        list.set(0, bTempData.get(3));
                        list.set(3, bTempData.get(0));
                    }
                } else if (GetCardValue(list.get(1)) == GetCardValue(laizi) && laizi != 0
                        || BasePockerLogic.isTrump(list.get(1))) {
                    if (GetCardValue(list.get(3)) == GetCardValue(laizi) && laizi != 0
                            || BasePockerLogic.isTrump(list.get(3))) {
                        list.set(1, bTempData.get(4));
                        list.set(4, bTempData.get(1));
                    } else {
                        list.set(1, bTempData.get(3));
                        list.set(3, bTempData.get(1));
                    }
                }
            }
            return 10;
        } else if (laiziNum == 0) {

            int result = 0;
            for (int i = 0; i < list.size(); i++) {
                result += bTemp.get(i);
            }
            result = result % 10;
            // 查找牛牛
            for (int i = 0; i < list.size(); i++) {
                // if(GetCardLogicValue(list.get(i)) == GetCardLogicValue(laizi) ||
                // BasePockerLogic.isTrump(list.get(i))){
                // continue;
                // }
                for (int j = i + 1; j < list.size(); j++) {
                    // if(GetCardLogicValue(list.get(j)) == GetCardLogicValue(laizi) ||
                    // BasePockerLogic.isTrump(list.get(j))){
                    // continue;
                    // }
                    if ((bSum - bTemp.get(i) - bTemp.get(j)) % 10 == 0) {
                        int bCount = 0;
                        for (int k = 0; k < list.size(); k++) {
                            if (k != i && k != j) {
                                list.set(bCount++, bTempData.get(k));
                            }
                        }
                        assert (bCount == 3);

                        list.set(bCount++, bTempData.get(i));
                        list.set(bCount++, bTempData.get(j));

                        if (result == 0) {
                            return 10;
                        }
                        return result;
                    }
                }

            }
        } else {
            // zhaozw癞子放到第一位
            for (int i = 0; i < list.size(); i++) {
                if (GetCardValue(list.get(i)) == GetCardValue(laizi) && laizi != 0
                        || BasePockerLogic.isTrump(list.get(i))) {

                    list.set(0, bTempData.get(i));
                    list.set(i, bTempData.get(0));
                    int temp = bTemp.get(i);
                    bTemp.set(i, bTemp.get(0));
                    bTemp.set(0, temp);
                    bTempData = (ArrayList<Integer>) list.clone();
                    break;
                }
            }
            // 查找牛牛
            for (int i = 1; i < list.size() - 1; i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    if ((bSum - bTemp.get(i) - bTemp.get(j)) % 10 == 0) {
                        int bCount = 1;
                        for (int k = 0; k < list.size(); k++) {
                            if (k == i || k == j) {
                                list.set(bCount++, bTempData.get(k));
                            }
                        }
                        assert (bCount == 3);

                        for (int k = 1; k < list.size(); k++) {
                            if (k != i && k != j) {
                                list.set(bCount++, bTempData.get(k));
                            }
                        }
                        // list.set(bCount++, bTempData.get(i));
                        // list.set(bCount++, bTempData.get(j));

                        return 10;
                    }
                }
            }

            // 查找牛牛
            for (int i = 1; i <= list.size() - 1; i++) {
                // for (int j=i+1;j<list.size();j++)
                {
                    if ((bSum - bTemp.get(i)) % 10 == 0) {
                        int bCount = 0;
                        for (int k = 1; k < list.size(); k++) {
                            if (k != i) {
                                list.set(bCount++, bTempData.get(k));
                            }
                        }
                        assert (bCount == 3);
                        list.set(bCount++, bTempData.get(0));
                        list.set(bCount++, bTempData.get(i));
                        // for (int k=1;k<list.size();k++)
                        // {
                        // if(k!=i && k!=j)
                        // {
                        // list.set(bCount++, bTempData.get(k));
                        // }
                        // }
                        // list.set(bCount++, bTempData.get(i));
                        // list.set(bCount++, bTempData.get(j));

                        return 10;
                    }
                }
            }

            // 四中取大
            int cbBigCount = 0;
            int cbBigIndex1 = 0;
            int cbBigIndex2 = 0;
            for (int i = 1; i < list.size(); i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    int cbSumCount = (GetCardLogicValue(list.get(i)) + GetCardLogicValue(list.get(j))) % 10;
                    if (cbSumCount > cbBigCount) {
                        cbBigIndex1 = i;
                        cbBigIndex2 = j;
                        cbBigCount = cbSumCount;
                    }
                }
            }

            // 四中取大
            int cbBigCount2 = 0;
            int cbBigIndex21 = 0;
            // int cbBigIndex2 = 0;
            for (int i = 1; i < list.size(); i++) {
                // for(int j = i + 1; j < list.size(); j++)
                {
                    int cbSumCount = (bSum - GetCardLogicValue(list.get(i))) % 10;
                    if (cbSumCount > cbBigCount2) {
                        cbBigIndex21 = i;
                        cbBigCount2 = cbSumCount;
                    }
                }
            }

            if (cbBigCount >= cbBigCount2 || true) {

                int cbCount = 0;
                list.set(cbCount++, bTempData.get(0));
                for (int i = 1; i < list.size(); i++) {
                    if (i != cbBigIndex1 && i != cbBigIndex2) {
                        list.set(cbCount++, bTempData.get(i));
                    }
                }

                list.set(cbCount++, bTempData.get(cbBigIndex1));
                list.set(cbCount++, bTempData.get(cbBigIndex2));

                return cbBigCount;
            } else {

                int cbCount = 0;
                for (int i = 1; i < list.size(); i++) {
                    if (i != cbBigIndex21) {
                        list.set(cbCount++, bTempData.get(i));
                    }
                }

                list.set(cbCount++, bTempData.get(0));
                list.set(cbCount++, bTempData.get(cbBigIndex21));

                return cbBigCount2;
            }
        }

        return 0;
    }

    // 逻辑数值
    public static Integer GetCardLogicValue(Integer cbCardData) {
        // 扑克属性
        Integer bCardValue = GetCardValue(cbCardData);

        // 转换数值
        return (bCardValue > 10) ? (10) : bCardValue;
    }

    public static Comparator<Integer> sorter = (left, right) -> {
        Integer v1 = NNGameLogic.GetCardValue(left);
        Integer v2 = NNGameLogic.GetCardValue(right);
        if (v1 == v2) {
            return NNGameLogic.GetCardColor(right) - NNGameLogic.GetCardColor(left);
        }
        return v2 - v1;
    };

    public static boolean CompareCard(ArrayList<Integer> cbLeftData, ArrayList<Integer> cbRightData, int laizi) {
        return CompareCard(cbLeftData, cbRightData, 5, laizi);
    }

    @SuppressWarnings("unchecked")
    public static boolean CompareCard(ArrayList<Integer> cbLeftData, ArrayList<Integer> cbRightData, int MAX_COUNT,
            int laizi) {
        if (cbLeftData.size() < 3 || cbLeftData.size() > MAX_COUNT) {
            return false;
        }
        // 这里先进行倍数比较
        int leftType = NNGameLogic.GetCardType(cbLeftData, laizi);
        int RightType = NNGameLogic.GetCardType(cbRightData, laizi);

        if (leftType != RightType)
            return leftType > RightType;

        ArrayList<Integer> tempLeftData = (ArrayList<Integer>) cbLeftData.clone();
        ArrayList<Integer> tempRightData = (ArrayList<Integer>) cbRightData.clone();

        tempLeftData.sort(sorter);
        tempRightData.sort(sorter);

        Integer cbLeftMaxValue = NNGameLogic.GetCardValue(tempLeftData.get(0));
        Integer cbRightMaxValue = NNGameLogic.GetCardValue(tempRightData.get(0));
        if (cbLeftMaxValue != cbRightMaxValue) {
            return cbLeftMaxValue > cbRightMaxValue;
        }
        // 比较颜色
        return GetCardColor(tempLeftData.get(0)) > GetCardColor(tempRightData.get(0));
    }

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList();
        list.add(8);
        list.add(6);
        list.add(22);
        list.add(9);
        // list.add(18);
        for (Integer integer : list) {
            System.out.println(GetCardValue(integer));
        }
        System.out.println("==============================");
        System.out.println(NNGameLogic.GetCardType(list, 0));
        System.out.println(NNGameLogic.GetCardType2(list, 0));

    }

    /**
     * 根据四张牌获取牌型
     *
     * @param list
     * @param laizi
     * @return
     */
    public static int GetCardType2(ArrayList<Integer> list, int laizi) {
        // 初始化结果值
        int result = 0;
        // 生成所有可能的3张牌组合
        ArrayList<ArrayList<Integer>> combinations = generateCombinations(list);
        // 遍历所有组合
        for (ArrayList<Integer> x : combinations) {
            // 判断当前3张牌组合的点数和是否为10的倍数
            if ((x.stream().mapToInt(NNGameLogic::GetCardValue2).sum() % 10) == 0) {
                // 复制原始牌组
                ArrayList<Integer> listNew = new ArrayList<>(list);
                // 移除已使用的3张牌
                removeAll(listNew, x);
                // 计算剩余1张牌的点数(1-10)
                int value = GetCardValue2(listNew.get(0)) % 10;
                value = value == 0 ? 10 : value;
                // 更新最大点数
                if (value > result) {
                    result = value;
                }
            }
        }
        return result;
    }

    /**
     * 从手牌中取出3张任意组合(不支持有重复元素)
     *
     * @param nums
     * @return
     */
    private static ArrayList<ArrayList<Integer>> generateCombinations(ArrayList<Integer> nums) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        backtracking(result, new ArrayList<>(), nums, 0);
        return result;
    }

    private static void backtracking(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> tempResult,
            ArrayList<Integer> nums, int startIndex) {
        if (tempResult.size() == 3) {
            result.add(new ArrayList<>(tempResult));
            return;
        }
        for (int i = startIndex; i < nums.size(); i++) {
            if (!tempResult.contains(nums.get(i))) {
                tempResult.add(nums.get(i));
                backtracking(result, tempResult, nums, i + 1);
                tempResult.remove(tempResult.size() - 1);
            }
        }
    }

    public static void removeAll(ArrayList<Integer> mAllList, ArrayList<Integer> mSubList) {
        // 第一步：构建mAllList的HashMap
        // 将mAllList中的元素作为键，如果不是String类，需要实现hashCode和equals方法
        // 将mAllList中的元素对应的位置作为值
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < mAllList.size(); i++) {
            map.put(mAllList.get(i), i);
        }
        // 第二步：利用map遍历mSubList，查找重复元素
        // 把mAllList中所有查到的重复元素的位置置空
        for (int i = 0; i < mSubList.size(); i++) {
            Integer pos = map.get(mSubList.get(i));
            if (pos == null) {
                continue;
            }
            mAllList.set(pos, null);
        }
        // 第三步：把mAllList中所有的空元素移除
        for (int i = mAllList.size() - 1; i >= 0; i--) {
            if (mAllList.get(i) == null) {
                mAllList.remove(i);
            }
        }
    }

}
